﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace CrossGenLogic
{
    public class Generation
    {
        private Crossword cross;
        private CSVReader reader;
        private int[] intervals;

        public Generation(string pathtovocabulary, string pathtogrid)
        {
            reader = new CSVReader();
            cross = new Crossword(reader.readgrid(pathtogrid), reader.readvoc(pathtovocabulary), 
                reader.Width, reader.Height);
            cross.SortVocabulary();
            SetIntervals();
        }
 
        public int CrossHeigth()
        {
            return cross.Height;
        }

        public int CrossWidth()
        {
            return cross.Width;
        }

        private void SetIntervals()
        {
            int i, j;
            intervals=new int[cross.GetWordByNumber(cross.WordsInVoc()-1).Length+1];
            for (i = 0; i < intervals.Length; i++)
            {
                for (j = 0; j < cross.WordsInVoc(); j++)
                {
                    if (cross.GetWordByNumber(j).Length == i)
                    {
                        intervals[i] = j;
                        break;
                    }
                }
            }
        }

        public char GetChar(int x, int y)
        {
            return cross.GetCharWithCount(x, y);
        }

        private bool CanPlace(GridElement GE, VocElement VE)
        {
            for (int i = 0; i < VE.Length; i++)
            {
                if (cross.GetCharWithCount(GE.X + i * GE.dx(), GE.Y + i * GE.dy()) != ' ' &&
                    cross.GetCharWithCount(GE.X + i * GE.dx(), GE.Y + i * GE.dy()) != VE.Word[i]) return false;
            }
            return true;
        }

        private void PlaceWord(GridElement GE, VocElement VE)
        {
            for (int i = 0; i < VE.Length; i++)
            {
                cross.SetCharWithCount(GE.X + i * GE.dx(), GE.Y + i * GE.dy(), VE.Word[i]);
            }
        }

        private void RemoveWord(GridElement GE)
        {
            for(int i=0; i<GE.Length;i++)
                cross.DecreaseCount(GE.X + i * GE.dx(), GE.Y + i * GE.dy());
        }

        public bool Generate(int WordIndex)
        {
            if (WordIndex == cross.WordsInCross()) return true;
            for (int p = intervals[cross.GetGEByNumber(WordIndex).Length]; 
                p < intervals[cross.GetGEByNumber(WordIndex).Length+1]; p++)
            {
                if (!cross.GetWordByNumber(p).Busy && CanPlace(cross.GetGEByNumber(WordIndex), cross.GetWordByNumber(p)))
                {
                    PlaceWord(cross.GetGEByNumber(WordIndex), cross.GetWordByNumber(p));
                    cross.SetBusy(p, true);
                    if (Generate(WordIndex + 1))
                        return true;
                    RemoveWord(cross.GetGEByNumber(WordIndex));
                    cross.SetBusy(p, false);
                }
            }
            return false; // ??
        }
    }
}
